package net.csdn.business.facade;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import net.csdn.business.common.domain.request.IssueDeleteReqDto;
import net.csdn.business.common.domain.request.IssueSaveReqDto;
import net.csdn.business.common.domain.request.IssueUpdateReqDto;
import net.csdn.business.common.domain.request.IssueUpdateStatusReqDto;
import net.csdn.business.common.domain.vo.IssueVo;
import net.csdn.business.common.domain.vo.migrate.MigrateInfoLogVo;
import net.csdn.business.common.enums.IssueEnum;
import net.csdn.business.common.enums.ResultCodeEnum;
import net.csdn.business.common.enums.UserTypeEnum;
import net.csdn.business.common.exception.BusinessException;
import net.csdn.business.common.utils.JsonUtil;
import net.csdn.business.enums.MigrateEnum;
import net.csdn.business.pojo.AtomGitIssue;
import net.csdn.business.pojo.AtomGitIssueComment;
import net.csdn.business.pojo.AtomGitLabel;
import net.csdn.business.pojo.AtomGitUser;
import net.csdn.business.util.ListDivider;
import net.csdn.business.util.MarkDownTansfer;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;

@Slf4j
@RequiredArgsConstructor
@Component
public class IssueFacade {


    //private final IssueFeignClient issueFeignClient;
    private final MigrateFacade migrateFacade;
    private final CommentFacade commentFacade;
    private final UserFacade userFacade;

    @Value("${grpc.atomgit.anonymous:65f906eb7af38bb6ff80fXXXX}")
    private String anonymous;

    @Value("${grpc.atomgit.issueDefaultConent:暂无内容}")
    private String issueDefaultConent;

    @Value("${grpc.atomgit.threadPoolSize:5}")
    private Integer threadPoolSize;


    public void saveIssue(Long repoId,String groupPath,String repoName, AtomGitIssue issue,  IssueSaveReqDto saveReqDto){
        //set labels
        List<AtomGitLabel> labelListList = issue.getLabelListList();
        if (CollectionUtils.isNotEmpty(labelListList)) {
            List<Long> lableIds = labelListList.stream().map(AtomGitLabel::getId).collect(Collectors.toList());
            List<String> lableIdsStr = Lists.transform(lableIds, i -> {
                return String.valueOf(i);
            });
            List<MigrateInfoLogVo> migrateInfoLogVos = migrateFacade.queryLogs(MigrateEnum.MigrateInfoTypeEnum.LABEL.code, lableIdsStr, groupPath, "");
            List<String> lableIdsMigrate = Lists.transform(migrateInfoLogVos, i -> {
                return i.getObjectId();
            });
            if(!CollectionUtils.isEmpty(lableIdsMigrate)){
                saveReqDto.setLabelIds(lableIdsMigrate);
            }
        }

        //save issue
        MigrateInfoLogVo vo = migrateFacade.queryLog(MigrateEnum.MigrateInfoTypeEnum.ISSUE.code, String.valueOf(issue.getId()), groupPath, String.valueOf(repoId));
        IssueUpdateReqDto issueUpdateReqDto = new IssueUpdateReqDto();
        IssueVo issueVo = null;
        if(ObjectUtils.isEmpty(vo.getId())){
            //需要 save
            //issueVo = issueFeignClient.save(saveReqDto);
            vo.setObjectId(issueVo.getIssueId());
            vo.setStatus(MigrateEnum.Status.SUCCESS.code);
            migrateFacade.save(vo);
        }else{
            //需要 update
            try {
                //issueVo = issueFeignClient.detail(vo.getObjectId());
            } catch (Exception e) {
                log.error("issue:{} saveIssue Exception:{}",JsonUtil.toJsonString(vo), JsonUtil.toJsonString(e));
            }
            //check 用户是否变更
            Map map = deleteIssueWithLog(issueVo, saveReqDto, groupPath, String.valueOf(repoId), issue.getCommentListList());
            Boolean deleteFlag = (Boolean) map.getOrDefault("deleteFlag", false);
            if(!deleteFlag){
                issueUpdateReqDto.setTitle(saveReqDto.getTitle());
                issueUpdateReqDto.setContent(saveReqDto.getContent());
                issueUpdateReqDto.setMdContent(saveReqDto.getMdContent());
            }
            issueVo = (IssueVo) map.get("issueVo");
            vo.setObjectId(issueVo.getIssueId());
            vo.setStatus(MigrateEnum.Status.SUCCESS.code);
            migrateFacade.save(vo);
        }


        // save or update comment
        commentFacade.saveCommentList(issue.getCommentListList(),String.valueOf(repoId),groupPath,repoName,issueVo.getIssueId(),saveReqDto.getProjectId());

        String state = issue.getState();
        IssueEnum.StatusEnum statusEnum = IssueEnum.StatusEnum.ofKeyDefault(state);
        if ( statusEnum.getCode() != issueVo.getStatus()) {
            //update issue state
            IssueUpdateStatusReqDto issueUpdateStatusReqDto = new IssueUpdateStatusReqDto();
            issueUpdateStatusReqDto.setIssueId(issueVo.getIssueId());
            String issueState = issue.getIssueState();
            IssueEnum.MigrateStatusReasonEnum migrateStatusReasonEnum = IssueEnum.MigrateStatusReasonEnum.ofKey(issueState);
            issueUpdateStatusReqDto.setUid(issueVo.getUid());
            issueUpdateStatusReqDto.setUpdatedDate(saveReqDto.getUpdatedDate());
            issueUpdateStatusReqDto.setClosedDate(saveReqDto.getClosedDate());
            issueUpdateStatusReqDto.setStatus(statusEnum.getCode());
            issueUpdateStatusReqDto.setStatusReason(migrateStatusReasonEnum.getCode());
            try {
                //issueFeignClient.updateStatus(issueUpdateStatusReqDto);
            } catch (Exception e) {
                log.error("issue:{} saveIssue updateStatus Exception:{}",JsonUtil.toJsonString(vo), JsonUtil.toJsonString(e));
            }
        }

        issueUpdateReqDto.setIssueId(issueVo.getIssueId());
        issueUpdateReqDto.setUid(issueVo.getUid());
        issueUpdateReqDto.setUpdatedDate(saveReqDto.getUpdatedDate());
        //更新里程碑
        if(ObjectUtils.isNotEmpty(issue.getMileStone())){
            MigrateInfoLogVo mileStoneVo = migrateFacade.queryLog(MigrateEnum.MigrateInfoTypeEnum.MILESTONE.code, String.valueOf(issue.getMileStone().getId()), groupPath, String.valueOf(repoId));
            String mileStoneId = mileStoneVo.getObjectId();
            if(ObjectUtils.isNotEmpty(mileStoneId)){
                issueUpdateReqDto.setMilepostId(mileStoneId);
            }
        }
       // issueFeignClient.update(issueUpdateReqDto);
    }

    public Integer importAtomGitIssueExcutor(List<AtomGitIssue> list,String adminUid,Long repoId,String repoGroupName,String repoName) throws Exception{
        ExecutorService executorService = Executors.newFixedThreadPool(threadPoolSize);
        Integer totalSum = 0;
        List<List<AtomGitIssue>> lists = ListDivider.divideList(list,threadPoolSize);
        List<Future<Integer>> futures = new ArrayList<>();
        for (List<AtomGitIssue> userList: lists) {
            Callable<Integer> task = () ->{
                return importAtomGitIssueThread(userList,adminUid,repoId,repoGroupName,repoName);
            };
            futures.add(executorService.submit(task));
        }
        // 等待所有线程执行结束并计算总和
        for (Future<Integer> future : futures) {
            totalSum += future.get();
        }
        //importAtomGitIssueThread(list,adminUid,projectVo,repoId,repoGroupName,repoName);
        executorService.shutdown();
        return totalSum;
    }
    public Integer importAtomGitIssueThread(List<AtomGitIssue> list,String adminUid,Long repoId,String repoGroupName,String repoName){
        AtomicReference<Integer> succesNum = new AtomicReference<>(0);
        list.forEach(issue->{
            try {
                IssueSaveReqDto saveReqDto = new IssueSaveReqDto();
                AtomGitUser creator = issue.getCreator();
                String uid = userFacade.queryForMigrateUser(creator);
                if(StringUtils.isEmpty(uid)){
                    uid = adminUid;
                }
                saveReqDto.setUid(uid);
                //saveReqDto.setProjectId(projectVo.getId());
                saveReqDto.setUserType(UserTypeEnum.USER.getType());
                if(StringUtils.isBlank(issue.getBody())){
                    saveReqDto.setContent(MarkDownTansfer.toHtml(issueDefaultConent));
                    saveReqDto.setMdContent(issueDefaultConent);
                }else{
                    saveReqDto.setContent(MarkDownTansfer.toHtml(issue.getBody()));
                    saveReqDto.setMdContent(issue.getBody());
                }

                saveReqDto.setTitle(issue.getTitle());
                saveReqDto.setPrivacy(0);
                saveReqDto.setCreatedDate(new Date(issue.getCreatedAt()*1000));
                saveReqDto.setUpdatedDate(new Date(issue.getUpdatedAt()*1000));
                if(issue.getFinishAt()>0){
                    saveReqDto.setClosedDate(new Date(issue.getFinishAt()*1000));
                }
                saveReqDto.setMigrateFlag(true);
                saveIssue(repoId, repoGroupName,repoName,issue,saveReqDto);
                succesNum.getAndSet(succesNum.get()+1);
            } catch (Exception e) {
                log.error("importAtomGitIssue issue:{} error:{}", issue.getId(), JsonUtil.toJsonString(e));
            }
        });
        return succesNum.get();
    }


    public Integer importAtomGitIssue(Long repoId,String repoGroupName, String repoName, List<AtomGitIssue> issueList) throws Exception{
        //ProjectVo projectVo = migrateFacade.getProjectDetailByPath(repoGroupName + "/" + repoName);
/*
        if(ObjectUtils.isEmpty(projectVo)){
            throw new BusinessException(ResultCodeEnum.RESOURCE_NOT_EXIST);
        }*/
        //找到项目管理员
        //String adminUid = userFacade.getAdminUserIdByProjectId(repoGroupName,repoName);
        return importAtomGitIssueExcutor(issueList, anonymous,repoId,repoGroupName,repoName);
    }

    /**
     *
     * @param issueVo
     * @param saveReqDto
     * @param groupPath
     * @param repoId
     * @param commentList
     */
    public Map deleteIssueWithLog(IssueVo issueVo, IssueSaveReqDto saveReqDto, String groupPath, String repoId, List<AtomGitIssueComment> commentList){
        Map result = Maps.newHashMap();
        Boolean deleteFlag = false;
        if(ObjectUtils.isEmpty(issueVo)||!issueVo.getUid().equals(saveReqDto.getUid())){
            //两次操作不是同一个用户？？ 删除数据，再来一遍 ,issue 已经被删除了，在保存一遍
            if(!ObjectUtils.isEmpty(issueVo)){
                IssueDeleteReqDto issueDeleteReqDto = new IssueDeleteReqDto();
                issueDeleteReqDto.setIssueId(issueVo.getIssueId());
                issueDeleteReqDto.setUid(issueVo.getUid());
                //issueFeignClient.delete(issueDeleteReqDto);
            }
            //删除issue 下的评论导入记录 重新关联导入
            MigrateInfoLogVo migrateInfoLogVo = new MigrateInfoLogVo();
            migrateInfoLogVo.setType(MigrateEnum.MigrateInfoTypeEnum.COMMENT.code);
            migrateInfoLogVo.setOriginGroupPath(groupPath);
            migrateInfoLogVo.setOriginRepoId(repoId);
            migrateInfoLogVo.setStatus(MigrateEnum.Status.FAIL.code);
            commentList.forEach(i->{
                migrateInfoLogVo.setOriginId(String.valueOf(i.getId()));
                migrateFacade.update(migrateInfoLogVo);
            });
            //issueVo = issueFeignClient.save(saveReqDto);
            deleteFlag = true;
        }

        result.put("deleteFlag",deleteFlag);
        result.put("issueVo",issueVo);
        return result;
    }
}
